/*******************************************************************************
 * Copyright (c) 2007 TOPCASED. All rights reserved. This program
 * and the accompanying materials are made available under the terms of the
 * Eclipse Public License v1.0 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors: - Topcased contributors and others - initial API and implementation
 *******************************************************************************/
/**
 * This is a fork of the UML2Java Plug-in developed by Topcased and released under
 * the Eclipse EPL License. http://www.eclipse.org/legal/epl-v10.html
 * In accordance with the license, I have forked the UML2Java plugin and have adapted
 * it to suit the needs of a UML2QoS instrumentation code generator for PHP.
 * 
 * @author Alexandru Burdusel
 */
package org.topcased.uml2qos.services;

import java.util.ArrayList;
import java.util.Hashtable;

import org.eclipse.emf.common.util.EList;
import org.eclipse.uml2.uml.OpaqueBehavior;
import org.eclipse.uml2.uml.Property;
import org.topcased.uml2qos.utilities.Log;

import java.util.Collections;

/**
 * Class Attributes Services : methods for generating attributes of a class from the class diagram
 * 
 * @author Ariel RAMPHUL (Sopra Group - Toulouse)
 */
public class AttServices
{

    /**
     * Class Attributes Item : class for stocking an attribute properties
     */
    private class AttributeItem implements Comparable<AttributeItem>
    {

        private String name;

        private String type;

        private String visibility;

        private boolean isStatic;

        private boolean isReadOnly;

        private int upperValue;

        /**
         * Constructor for AttributeItem
         */
        public AttributeItem(String n, String t, String v, boolean isS, boolean isR, int uV)
        {
            name = n;
            type = t;
            visibility = v;
            isStatic = isS;
            isReadOnly = isR;
            upperValue = uV;
        }

        /**
         * This method compare 2 AttributeItem (comparison on visibility, public>protected>private) It is used in the
         * sort method of a Collection and allow us to generate the public attributes first, than the protected
         * attributes and finally the private attributes
         * 
         * @param att the second AttributeItem
         * @return An integer (0=both AttributeItem are equal, -1=the first AttributeItem is before the second and 1=the
         *         second AttributeItem if before the first one)
         */
        public int compareTo(AttributeItem att)
        {
            String a = "";
            String b = "";

            // String A
            if (this.visibility.compareTo("public") == 0)
            {
                a = "0";
            }
            if (this.visibility.compareTo("protected") == 0)
            {
                a = "1";
            }
            if (this.visibility.compareTo("private") == 0)
            {
                a = "2";
            }
            // String B
            if (att.visibility.compareTo("public") == 0)
            {
                b = "0";
            }
            if (att.visibility.compareTo("protected") == 0)
            {
                b = "1";
            }
            if (att.visibility.compareTo("private") == 0)
            {
                b = "2";
            }

            return a.compareTo(b);
        }

    }

    /**
     * Contain the attribute list
     */
    private ArrayList<AttributeItem> attList = new ArrayList<AttributeItem>();

    public void checkAttributes(org.eclipse.uml2.uml.Classifier c)
    {

        Hashtable<String, Integer> h = new Hashtable<String, Integer>();

        for (int i = 0; i < attList.size(); i++)
        {
            if (h.containsKey(attList.get(i).name))
            {
                Log.log("[02] Duplicate attribute name <" + attList.get(i).name + "> in the class or interface <" + c.getName() + ">.");
            }
            else
            {
                h.put(attList.get(i).name, 0);
            }
        }
    }

    /**
     * This method convert all attributes of a class in php and sort the attributes by visibility (public, then
     * protected and finally private attributes)
     * 
     * @param c is a UML Class
     * @return The generated string
     */
    public String genClassAttributes(org.eclipse.uml2.uml.Class c)
    {
        StringBuffer res = new StringBuffer("\n" + StringServices.addTab(1) + "//Attributes\n");
        EList<Property> l = c.getOwnedAttributes();
        Property p;

        if (c instanceof OpaqueBehavior)
        {
            return "";
        }

        // Parse attribute list
        attList.clear();
        for (int i = 0; i < l.size(); i++)
        {
            p = l.get(i);
            if (p.getType() != null)
            {
                attList.add(new AttributeItem(p.getName(), p.getType().getName(), p.getVisibility().toString(), p.isStatic(), p.isReadOnly(), p.getUpper()));
            }
            else
            {
                attList.add(new AttributeItem(p.getName(), "String", p.getVisibility().toString(), p.isStatic(), p.isReadOnly(), p.getUpper()));
                Log.log("[03] The attribute <" + p.getName() + "> in the class <" + c.getName() + "> doesn't have a type. It will be considered as a String.");
            }
        }
        checkAttributes(c);

        // Sort attributes by visibility
        Collections.sort(attList);

        // Generate attribute list
        for (int i = 0; i < l.size(); i++)
        {
            AttributeItem a = attList.get(i);

            if (a.upperValue <= 1)
            {
                if (!a.isReadOnly)
                {
                	res.append(CommentServices.generateComment(a.name,"Property",a.type));
                    res.append(StringServices.addTab(1) + a.visibility + PhpServices.stIsStaticToString(a.isStatic) + " $" + a.name + ";\n");
                }
                else
                {
                	res.append(CommentServices.generateComment(a.name,"Property",a.type));
                    res.append(StringServices.addTab(1) + a.visibility + PhpServices.stIsStaticToString(a.isStatic) + " $" + a.name + " = "
                            + PhpServices.stGetPhpDefaultValForType(a.type) + ";\n");
                }
            }
        }
        
        if (res.toString().compareTo("\n" + StringServices.addTab(1) + "//Attributes\n") == 0)
        {
            return "";
        }
        else
        {
            return res.toString();
        }

    }

}
